package com.hmall.annotation.impl;
import com.hdmall.business.common.annotation.AuthRequired;
import com.hdmall.business.common.annotation.LoginRequired;
import com.hmall.model.SysUser;
import com.hmall.service.UserService;
import com.hdmall.business.common.util.AgentUtil;
import com.hmall.util.DataFomateUtil;
import com.hmall.util.TokenUtil;
import com.hdmall.business.common.util.UserUtils;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.List;


/*Token验证过滤器，判断是否已经登陆*/
public class AuthenticationInterceptor  implements  HandlerInterceptor{

    @Autowired
    private UserService userService;

    @Autowired
    JedisPool jedisPool;


    @Override
    public  boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {


        //如果不是映射到方法直接通过
        if(!(handler instanceof HandlerMethod)){
            return true;
        }

        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();

        //判断是否有权限
        AuthRequired authRequired = method.getAnnotation(AuthRequired.class);
        if (authRequired != null) {
            List<String> list = UserUtils.getRole(request);
            for (int i=0;i<list.size();i++) {
                if (list.get(i).equals("ROLE_USER")){
                    list.remove(i);
                }
            }
            if (list.size()==0) {
                throw new RuntimeException("用户已失效,请重新登录");
            }else {
                return true;
            }
        }


        //判断接口是否需要登录
        LoginRequired methodAnnotation = method.getAnnotation(LoginRequired.class);
        //如果有@LoginRequired注解，需要认证
        if(methodAnnotation != null){

            //是从每个接口中获得的token
            String accessToken = request.getParameter("token");


            //登录失败
            if(null==accessToken|| accessToken.equals("")){
                throw new RuntimeException("无该用户,请重新登录");
            }

            Claims claims;
            try {
                claims = TokenUtil.parseJWT(accessToken);
            }catch (Exception e){
                e.printStackTrace();
                throw new RuntimeException("无该用户,请重新登录");
            }
            String agentUserName = claims.getId();
            String str[] = AgentUtil.deleteAgentUserName(agentUserName).getData().split(":");

            String agent = str[0];
            String userName = str[1];


            //判断出误传的token，实际并没有用户
            if(userName == null|| userName.equals("")){
                throw new RuntimeException("无该用户,请重新登录");
                //throw new RuntimeException("无该用户,请重新登录");
            }

            /*一.账号唯一性
            * 1.用户在不同位置登录，只能登录一个(pc,ios只能在一个地方登录)
            * 2.token超过3600s，失效
            * 将从前端页面得到的token和登陆时候传入到redis的新的token相比较
            * /

            /*二.手机电脑同步登录
            * ——————
            * 1.pc
            * 2.ios
            * 对于每个用户名传入设置为agent+userName
            * ——————
            * 3.微信
            * */

            Jedis jedis = jedisPool.getResource();
            String nowToken = jedis.get(agent + userName);
            jedis.close();

            if(null==nowToken){
                throw new RuntimeException("用户已失效,请重新登录");
            }

            if(nowToken.equals(accessToken) == false)  throw new RuntimeException("用户已失效,请重新登录");



            jedis = jedisPool.getResource();
            SysUser user;
            String key =  agent + userName + "REDIS_USER";
            //每次需要获得用户信息从redis中取
            if(jedis.get(key) != null) {
                String value = jedis.get(key);

                jedis.close();
                //将字符串形式的user转换成user
                user = DataFomateUtil.stringToSysUser(value);

            } else{
                //如果redis中不存在需要从数据库中进行查询，然后存到redis中
                user = userService.simpleUserByUsername(userName).getData();
                //可以
                //将user转换成字符串形式
                jedis.setex(key,3600 * 1000 * 24, DataFomateUtil.sysUserToString(user));
                jedis.close();
            }

            System.out.println("true");
            return true;
        }
        return true;
    }

    /*请求处理之后调用，在视图被渲染之前,controller方法之后调用*/
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }
    /*在整个请求结束后调用，在DispatcherServlet渲染了对应视图后执行,进行资源清理工作*/
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}
